from django.contrib import admin
from django.urls import path
from django.shortcuts import render, redirect
from django.http import HttpResponse, JsonResponse
from django.conf import settings
import os
from django.contrib import messages
from django.utils.html import format_html
from django.urls import reverse
from django.contrib.admin.views.decorators import staff_member_required
from django.views.decorators.csrf import csrf_exempt
from django import forms
from .models import File, ShortURL, FileIndex
import datetime
from file_manager.utils import rebuild_file_index
from django.core.cache import cache

class FileAdminForm(forms.ModelForm):
    """自定义表单，添加目录选择功能"""
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 改为 CharField 支持任意目录路径输入
        self.fields['upload_dir'] = forms.CharField(
            max_length=50,
            required=False,
            label='上传目录',
            help_text='选择文件上传到的目录，留空则上传到根目录。支持多级目录，如：文档/224'
        )
    
    class Meta:
        model = File
        fields = '__all__'

@admin.register(ShortURL)
class ShortURLAdmin(admin.ModelAdmin):
    list_display = ['original_url', 'short_code', 'created_at']
    search_fields = ['original_url', 'short_code']
    readonly_fields = ['short_code', 'created_at']

@admin.register(File)
class FileAdmin(admin.ModelAdmin):
    form = FileAdminForm
    list_display = ['name', 'upload_dir', 'file_size', 'upload_time']
    search_fields = ['name']
    readonly_fields = ['upload_time', 'file_size']
    list_filter = ['upload_time', 'upload_dir']
    
    class Media:
        js = ('js/file_admin.js',)
    
    def get_urls(self):
        urls = super().get_urls()
        custom_urls = [
            path('get_directories/', self.admin_site.admin_view(self.get_directories_view), name='get_directories'),
            path('create_directory/', self.admin_site.admin_view(self.create_directory_view), name='create_directory'),
            path('file_upload/', self.admin_site.admin_view(self.upload_view), name='file_upload'),
            path('file_delete/', self.admin_site.admin_view(self.delete_view), name='file_delete'),
            path('file_rename/', self.admin_site.admin_view(self.rename_view), name='file_rename'),
            path('rebuild_index/', self.admin_site.admin_view(self.rebuild_index_view), name='rebuild_index'),
        ]
        return custom_urls + urls
    
    def get_directories_view(self, request):
        """获取 file_storage 下的目录列表（支持多级目录）"""
        if not request.user.is_staff:
            return JsonResponse({'error': '权限不足'}, status=403)
        
        def get_directories_recursive(base_path, current_path=''):
            """递归获取目录结构"""
            dirs = []
            full_path = os.path.join(base_path, current_path)
            
            if os.path.exists(full_path):
                for item in os.listdir(full_path):
                    item_path = os.path.join(full_path, item)
                    if os.path.isdir(item_path):
                        # 构建相对路径
                        relative_path = os.path.join(current_path, item) if current_path else item
                        dirs.append(relative_path)
                        # 递归获取子目录
                        sub_dirs = get_directories_recursive(base_path, relative_path)
                        dirs.extend(sub_dirs)
            return dirs
        
        dirs = get_directories_recursive(settings.FILE_ROOT)
        return JsonResponse({'directories': sorted(dirs)})
    
    def create_directory_view(self, request):
        """创建目录视图"""
        if not request.user.is_staff:
            return JsonResponse({'error': '权限不足'}, status=403)
        if request.method == 'POST':
            dir_path = request.POST.get('dir_path', '').strip()
            if not dir_path:
                return JsonResponse({'error': '目录路径不能为空'}, status=400)
            try:
                full_path = os.path.join(settings.FILE_ROOT, dir_path)
                os.makedirs(full_path, exist_ok=True)
                return JsonResponse({'success': True, 'message': f'目录 {dir_path} 创建成功'})
            except Exception as e:
                return JsonResponse({'error': f'创建目录失败: {str(e)}'}, status=500)
        return JsonResponse({'error': '请求方法不支持'}, status=405)
    
    def save_model(self, request, obj, form, change):
        # 自动设置文件名
        if obj.file and not obj.name:
            obj.name = os.path.basename(obj.file.name)
        # 确保目录存在（支持多级目录）
        if obj.upload_dir:
            dir_path = os.path.join(settings.FILE_ROOT, obj.upload_dir)
            os.makedirs(dir_path, exist_ok=True)
        super().save_model(request, obj, form, change)

    @staff_member_required
    def upload_view(self, request):
        """文件上传视图"""
        if request.method == 'POST':
            files = request.FILES.getlist('files')
            path = request.POST.get('path', settings.FILE_ROOT)
            upload_success = False
            for file in files:
                try:
                    file_path = os.path.join(path, file.name)
                    with open(file_path, 'wb+') as destination:
                        for chunk in file.chunks():
                            destination.write(chunk)
                    # --- 新增：写入FileIndex ---
                    rel_path = os.path.relpath(file_path, settings.FILE_ROOT).replace('\\', '/')
                    stat = os.stat(file_path)
                    FileIndex.objects.update_or_create(
                        path=rel_path,
                        defaults={
                            'name': file.name,
                            'size': stat.st_size,
                            'mtime': datetime.datetime.fromtimestamp(stat.st_mtime),
                            'is_dir': False
                        }
                    )
                    messages.success(request, f'文件 {file.name} 上传成功')
                    upload_success = True
                except Exception as e:
                    messages.error(request, f'文件 {file.name} 上传失败: {str(e)}')
            # 上传成功后清理文件列表相关缓存
            if upload_success:
                cache_key_prefix = "file_list:"
                for key in list(cache._cache.keys()):
                    if key.startswith(cache_key_prefix):
                        cache.delete(key)
            return redirect(reverse('admin:file_upload'))
        
        return render(request, 'admin/file_upload.html', {
            'title': '上传文件',
            'opts': self.model._meta,
            'has_change_permission': self.has_change_permission(request)
        })

    @staff_member_required
    def delete_view(self, request):
        """文件删除视图"""
        if request.method == 'POST':
            file_paths = request.POST.getlist('file_paths')
            for file_path in file_paths:
                try:
                    if os.path.exists(file_path):
                        rel_path = os.path.relpath(file_path, settings.FILE_ROOT).replace('\\', '/')
                        if os.path.isdir(file_path):
                            os.rmdir(file_path)
                            FileIndex.objects.filter(path=rel_path).delete()
                        else:
                            os.remove(file_path)
                            FileIndex.objects.filter(path=rel_path).delete()
                        messages.success(request, f'成功删除: {file_path}')
                    else:
                        messages.error(request, f'文件不存在: {file_path}')
                except Exception as e:
                    messages.error(request, f'删除失败 {file_path}: {str(e)}')
            
            return redirect(reverse('admin:file_delete'))
        
        return render(request, 'admin/file_delete.html', {
            'title': '删除文件',
            'opts': self.model._meta,
            'has_change_permission': self.has_change_permission(request)
        })

    @staff_member_required
    def rename_view(self, request):
        """文件重命名视图"""
        if request.method == 'POST':
            old_path = request.POST.get('old_path')
            new_name = request.POST.get('new_name')
            
            if not old_path or not new_name:
                messages.error(request, '请提供完整参数')
                return redirect(reverse('admin:file_rename'))
            
            try:
                dir_path = os.path.dirname(old_path)
                new_path = os.path.join(dir_path, new_name)
                
                if os.path.exists(new_path):
                    messages.error(request, '目标文件名已存在')
                else:
                    os.rename(old_path, new_path)
                    # --- 新增：更新FileIndex ---
                    rel_old = os.path.relpath(old_path, settings.FILE_ROOT).replace('\\', '/')
                    rel_new = os.path.relpath(new_path, settings.FILE_ROOT).replace('\\', '/')
                    FileIndex.objects.filter(path=rel_old).update(path=rel_new, name=new_name, mtime=datetime.datetime.now())
                    messages.success(request, f'重命名成功: {os.path.basename(old_path)} → {new_name}')
            except Exception as e:
                messages.error(request, f'重命名失败: {str(e)}')
            
            return redirect(reverse('admin:file_rename'))
        
        return render(request, 'admin/file_rename.html', {
            'title': '重命名文件',
            'opts': self.model._meta,
            'has_change_permission': self.has_change_permission(request)
        })

    def rebuild_index_view(self, request):
        """重建文件索引表视图"""
        from django.contrib import messages
        try:
            count = rebuild_file_index()
            messages.success(request, f'索引重建成功！共索引 {count} 个文件/目录。')
        except Exception as e:
            messages.error(request, f'索引重建失败：{str(e)}')
        return redirect(reverse('admin:file_manager_file_changelist'))

    def changelist_view(self, request, extra_context=None):
        """重写列表视图添加自定义按钮"""
        extra_context = extra_context or {}
        extra_context['file_root'] = settings.FILE_ROOT
        extra_context['show_directory_management'] = True
        return super().changelist_view(request, extra_context=extra_context)

# 恢复默认admin标题设置
admin.site.site_header = '文件管理后台'
admin.site.site_title = '文件管理系统后台'
admin.site.index_title = '欢迎进入文件管理后台'
